package com.coder.algorithm.struct;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Random;

/**
 * @author Sam
 */
public class HashMapTester {

    public static void main(String[] args) {
        try {
            runTest();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    static final float LOAD_FACTOR = 0.75f;
    Field thresholdField;

    private void initFiled() {
        Class<?> hashMapClass = HashMap.class;
        try {
            thresholdField = hashMapClass.getDeclaredField("threshold");
            thresholdField.setAccessible(true);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

    public static void runTest() throws IllegalAccessException {
        HashMapTester tester = new HashMapTester();
        // 1,2,4,8,16,32,64,128,256,512,1024
        int count = 1024;
        for (int size = 1; size <= count; size++) {
            int threshold = tester.getThreshold(size, (int) (size / LOAD_FACTOR));
            int addThreshold = tester.getThreshold(size, (int) (size / LOAD_FACTOR) + 1);

            if (threshold != addThreshold) {
                int capacity = (int) (threshold / LOAD_FACTOR);
                int addCapacity = (int) (addThreshold / LOAD_FACTOR);
                System.out.format("不加1的情况初始化容量：%d, [阈值, 容量] = [%d, %d]\n", size, capacity, threshold);
                System.out.format("加上1的情况初始化容量：%d, [阈值, 容量] = [%d, %d]\n", size, addCapacity, addThreshold);
                System.out.println();
            }
        }
    }

    public int getThreshold(int size, int initialCapacity) throws IllegalAccessException {
        if (thresholdField == null) {
            initFiled();
        }
        HashMap<Integer, Integer> map = new HashMap<>(initialCapacity);
        Random random = new Random(47);
        int threshold = 0, oldTh = 0;
        for (int i = 0; i < size; i++) {
            map.put(random.nextInt(), i);
            threshold = (int) thresholdField.get(map);
            if (oldTh == 0) {
                oldTh = threshold;
            } else if (oldTh != threshold) {
                System.out.format("发生了扩容：由[%d -> %d]\n", oldTh, threshold);
                oldTh = threshold;
            }
        }
        return threshold;
    }
}
